#pragma once
#include <iostream>
#include <string>
#include <cstring>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <jsoncpp/json/json.h>

// #define MYSELF 0
#define SPACE " "
#define SPACE_LEN strlen(SPACE)
#define SEP "\r\n"
#define SEP_LEN strlen(SEP) // 不能是sizeof！

// 请求
class Request
{
public:
    Request()
    {
    }
    Request(int x, int y, char op) : _x(x), _y(y), _op(op)
    {
    }
    ~Request()
    {
    }

    // 序列化
    std::string Serialize()
    {
#ifdef MYSELF
        std::string str;
        str = std::to_string(_x);
        str += SPACE;
        str += _op; // TODO
        str += SPACE;
        str += std::to_string(_y);
        return str;
#else
        Json::Value root;
        root["x"] = _x;
        root["y"] = _y;
        root["op"] = _op;
        Json::FastWriter writer;
        return writer.write(root);
#endif
    }

    // 反序列化
    // x op y
    bool Deserialized(const std::string &str)
    {
#ifdef MYSELF
        std::size_t left = str.find(SPACE);
        if (left == std::string::npos)
        {
            return false;
        }
        std::size_t right = str.rfind(SPACE);
        if (right == std::string::npos)
        {
            return false;
        }
        _x = atoi(str.substr(0, left).c_str());
        _y = atoi(str.substr(right + SPACE_LEN).c_str());
        if (left + SPACE_LEN > str.size())
            return false;
        else
            _op = str[left + SPACE_LEN];
        return true;
#else
        Json::Value root;
        Json::Reader reader;
        reader.parse(str, root);
        _x = root["x"].asInt();
        _y = root["y"].asInt();
        _op = root["op"].asInt();
        return true;
#endif
    }

public:
    int _x;
    int _y;
    char _op;
};

// 回应
class Response
{
public:
    Response()
    {
    }
    Response(int result, int code, int x, int y, char op)
        : _result(result), _code(code), _x(x), _y(y), _op(op)
    {
    }
    ~Response()
    {
    }

    // 序列化
    std::string Serialize()
    {
#ifdef MYSELF
        std::string str;
        str = std::to_string(_code);
        str += SPACE;
        str += std::to_string(_result);
        return str;
#else
        Json::Value root;
        root["code"] = _code;
        root["result"] = _result;
        root["xx"] = _x;
        root["yy"] = _y;
        root["op"] = _op;
        Json::FastWriter writer;
        return writer.write(root);
#endif
    }

    // 反序列化
    // code result
    bool Deserialized(const std::string &str)
    {
#ifdef MYSELF
        std::size_t pos = str.find(SPACE);
        if (pos == std::string::npos)
        {
            return false;
        }
        _code = atoi(str.substr(0, pos).c_str());
        _result = atoi(str.substr(pos + SPACE_LEN).c_str());
        return true;
#else
        Json::Value root;
        Json::Reader reader;
        reader.parse(str,root);
        _code=root["code"].asInt();
        _result=root["result"].asInt();
        _x = root["x"].asInt();
        _y = root["y"].asInt();
        _op = root["op"].asInt();
        return true;
#endif
    }

public:
    int _code;
    int _result;
    int _x;
    int _y;
    char _op;
};
bool Recv(int sock, std::string *out)
{
    // UDP是面向数据报:
    // TCP 面向字节流的:
    // recv ： 你怎么保证，你读到的inbuffer，是一个完整完善的请求呢？不能保证
    // "1234 + 5678" : 1234 +
    // "1234 + 5678" : 1234 + 5678 123+99
    // "1234 "
    // 必须是："1234 + 5678"
    // 单纯的recv是无法解决这个问题的，需要对协议进一步定制！
    char buffer[1024];
    ssize_t s = recv(sock, buffer, sizeof(buffer) - 1, 0); // 9\r\n123+789\r\n
    if (s > 0)
    {
        buffer[s] = 0;
        *out += buffer;
    }
    else if (s == 0)
    {
        std::cout << "client quit" << std::endl;
        return false;
    }
    else
    {
        std::cout << "recv error" << std::endl;
        return false;
    }
    return true;
    std::cout << "recv success" << std::endl;
}
void Send(int sock, const std::string &str)
{
    int n = send(sock, str.c_str(), str.size(), 0);
    if (n < 0)
        std::cout << "send error" << std::endl;
}
// 解包
std::string Decode(std::string &buffer)
{
    std::size_t pos = buffer.find(SEP);
    if (pos == std::string::npos)
        return "";
    int size = atoi(buffer.substr(0, pos).c_str());
    int surplus = buffer.size() - pos - 2 * SEP_LEN;
    if (surplus >= size)
    {
        // 至少具有一个合法完整的报文, 可以动手提取了
        buffer.erase(0, pos + SEP_LEN);
        std::string s = buffer.substr(0, size);
        buffer.erase(0, size + SEP_LEN);
        return s;
    }
    else
    {
        return "";
    }
}
// 添加
//  "XXXXXX"
//  "123\r\nXXXXXX\r\n"
std::string Encode(std::string &s)
{
    std::string new_package = std::to_string(s.size());
    new_package += SEP;
    new_package += s;
    new_package += SEP;
    return new_package;
}
